import {spawn} from 'node:child_process'

import {promisifyProcess} from './general-util.js'

// Some probers are sorta inconsistent; this function lets them try again if
// they fail the first time.
const tryAgain = function(times, func) {
  return async function(...args) {
    let n = 0
    let ret
    while (!ret && n < times) {
      try {
        ret = await func(...args)
      } catch (error) {
        if (n + 1 === times) {
          throw error
        }
      }
      n++
    }
    return ret
  }
}

const metadataReaders = {}

metadataReaders.ffprobe =
  tryAgain(6, async filePath => {
    const ffprobe = spawn('ffprobe', [
      '-print_format', 'json',
      '-show_entries', 'stream=codec_name:format',
      '-select_streams', 'a:0',
      '-v', 'quiet',
      filePath
    ])

    let probeDataString = ''

    ffprobe.stdout.on('data', data => {
      probeDataString += data
    })

    try {
      await promisifyProcess(ffprobe, false)
    } catch (error) {
      return null
    }

    let data

    try {
      data = JSON.parse(probeDataString)
    } catch (error) {
      return null
    }

    if (typeof data !== 'object' || typeof data.format !== 'object') {
      return null
    }

    return {
      duration: parseFloat(data.format.duration),
      fileSize: parseInt(data.format.size),
      bitrate: parseInt(data.format.bit_rate)
    }
  })

export default metadataReaders

export function getMetadataReaderFor(_arg) {
  // Only the one metadata reader implemented, so far!
  return metadataReaders.ffprobe
}
